/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.opensudoku.root.fon;

//Importing required packages
import java.util.Vector;

import org.opensudoku.root.exceptions.InvalidBoxEntryException;
import org.opensudoku.root.exceptions.InvalidDimensionException;
import org.opensudoku.root.exceptions.UnIntializedParameterException;
import org.opensudoku.root.vsb.VirtualSudokuBoard;

/**
 *
 * @author sony
 */

//The Fon-First One Normalize Class
public class Fon {

    //Sudoku Board & void vector
    private VirtualSudokuBoard FonsBoard=null;
    private Vector<voidClass> FonsVoidVector=null;
    public Fon()
    {
        this.FonsBoard=null;
    }
    public Fon(VirtualSudokuBoard vsb)
    {
        this.FonsBoard=vsb;
    }
    private void FonAnalysis() throws UnIntializedParameterException, InvalidDimensionException
    {
        voidClass vc=null;
        if(this.FonsBoard==null)
            throw new UnIntializedParameterException("\'Fon.FonsBoard\'");
        this.FonsVoidVector=new Vector<voidClass>();
        for(int i=1;i<=9;i++)
            for(int j=1;j<=9;j++)
                if(this.FonsBoard.getEntry(i, j)==0)
                {
                    vc=new voidClass(i,j);
                    vc.setPosList(vc.FonCP_AI(this.FonsBoard));
                    this.FonsVoidVector.add(vc);
                }
    }

    private boolean IsOne(int[] x)
    {
        int count=0;
        for(int c:x)
            if(c>0)
                count++;
        return count==1;
    }
    private voidClass FonGetNextVoid()
    {
        for(Object vc : this.FonsVoidVector)
            if(IsOne(((voidClass)vc).getPosList())&&((voidClass)vc).isNotProcessed())
                return ((voidClass)vc);
        return null;
    }

    private int getOne(int[] x)
    {
        for(int c:x)
            if(c>0)
                return c;
        return 0;
    }
    private void FonSetNextVoid(voidClass vc) throws InvalidDimensionException, InvalidBoxEntryException
    {
        vc.setFonsFlag(true);
        this.FonsBoard.update(vc.getRow(), vc.getCol(), getOne(vc.getPosList()));
    }

    private int FonCurrentNormalize() throws InvalidDimensionException, InvalidBoxEntryException
    {
        int count=0;
        voidClass vc;
        while((vc=this.FonGetNextVoid())!=null)
        {
            this.FonSetNextVoid(vc);
            count++;
        }
        return count;
    }

    public FonResults doFon() throws UnIntializedParameterException, InvalidDimensionException, InvalidBoxEntryException
    {
        FonResults FonResult=new FonResults();
        int count=0;

        this.FonAnalysis();

        FonResult.noOfVoidsBeforeFon=this.FonsBoard.getnoOfVoids();
        while(this.FonCurrentNormalize()!=0)
        {
            this.FonAnalysis();
            count++;
        }
        FonResult.FonSolutionBoard=this.FonsBoard;
        FonResult.noOfVoidsAfterFon=this.FonsBoard.getnoOfVoids();
        if(FonResult.noOfVoidsAfterFon>0)
        {
            this.FonAnalysis();
            FonResult.ConcreteFlag=true;
            FonResult.FonAfterVoids=this.FonsVoidVector;
        }
        FonResult.FonSteps=count;
        return FonResult;
    }

    public static void displayFonResults(FonResults FonResult)
    {
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
        System.out.println("Fon Statistics...\n******************");
        System.out.println("No. Of Voids before Fon: "+FonResult.noOfVoidsBeforeFon);
        System.out.println("No. Of Voids after Fon: "+FonResult.noOfVoidsAfterFon);
        System.out.println("Status of Concrete Flag: "+FonResult.ConcreteFlag);
        System.out.println("Board Status after Fon: \n******************");
        FonResult.FonSolutionBoard.printBoard();
        System.out.println("Fon Completed in "+ FonResult.FonSteps+" passes.");
        System.out.println("~~~~~~~~~~~~~~~~~~~~~~~");
    }
}